package com.lovcreate.shop.mgt.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.openservices.log.Client;
import com.aliyun.openservices.log.common.LogContent;
import com.aliyun.openservices.log.common.QueriedLog;
import com.aliyun.openservices.log.exception.LogException;
import com.aliyun.openservices.log.request.GetHistogramsRequest;
import com.aliyun.openservices.log.request.GetLogsRequest;
import com.aliyun.openservices.log.response.GetHistogramsResponse;
import com.aliyun.openservices.log.response.GetLogsResponse;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.*;
import org.apache.commons.lang.StringUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 文件名：LogUtil
 * 创建人：victor
 * 创建日期 2017-02-15
 * 描  述：日志帮助类
 * 版本号： 1.0
 **/
public class LogUtil {

    private static Client client = new Client(LogProperty.endpoint, LogProperty.accessKeyId, LogProperty.accessKeySecret);
    private static OSSClient ossClient = new OSSClient(LogProperty.ossEndpoint, LogProperty.accessKeyId, LogProperty.accessKeySecret);

    /**
     * 查询日志
     *
     * @param topic     标题
     * @param query     关键字
     * @param startDate 开始时间
     * @param endDate   截止时间
     * @param logStore  log库
     * @return JSONArray
     */
    public static JSONArray getLog(String topic, String query, String startDate, String endDate, String logStore) {
        topic = StringUtils.isEmpty(topic) ? "" : topic;
        query = StringUtils.isEmpty(topic) ? "" : query;
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if (StringUtils.isEmpty(startDate) || StringUtils.isEmpty(endDate))
            return new JSONArray();
//        startDate = StringUtils.isEmpty(startDate) ? dateFormat.format(new Date()) : startDate;
//        endDate = StringUtils.isEmpty(endDate) ? dateFormat.format(new Date()) : endDate;
        int from = 0;
        int to = 1;
        try {
            from = (int) (dateFormat.parse(startDate).getTime() / 1000 - 10000);
            to = (int) (dateFormat.parse(endDate).getTime() / 1000 + 10);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        GetHistogramsResponse hisResp = null;
        boolean completed = false;
        int retry_time = 0;
        while (retry_time < 10) {
            GetHistogramsRequest reqHis = new GetHistogramsRequest(LogProperty.project,
                    logStore, topic, query, from, to);
            try {
                hisResp = client.GetHistograms(reqHis);
            } catch (LogException e) {
                e.printStackTrace();
                break;
            }
            if (hisResp != null && hisResp.IsCompleted()) // IsCompleted() 返回 true，表示查询结果是准确的，如果返回 false，则重复查询
            {
                completed = hisResp.IsCompleted();
                break;
            }
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
                break;
            }
            retry_time++;
        }
        JSONArray jsArray = new JSONArray();
        if (completed)
            jsArray = getLogs(hisResp, from, to, topic, query);
        return jsArray;
    }

    /**
     * 查询日志
     *
     * @param res   日志分布请求
     * @param from  开始时间
     * @param to    结束时间
     * @param topic 标题
     * @param query 查询关键字
     * @return JSONArray
     */
    private static JSONArray getLogs(GetHistogramsResponse res, int from, int to, String topic, String query) {
        // 查询日志数据
        JSONArray jsArray = new JSONArray();
        //List logList = new ArrayList();
        long total_log_lines = res.GetTotalCount();
        int log_offset = 0;
        int log_line = 10;
        while (log_offset <= total_log_lines) {
            GetLogsResponse logResp = null;
            // 对于每个 log offset,一次读取 10 行 log，如果读取失败，最多重复读取 3 次。
            for (int retry_time = 0; retry_time < 3; retry_time++) {
                GetLogsRequest req4 = new GetLogsRequest(LogProperty.project, LogProperty.logStore_pay,
                        from, to, topic, query, log_offset, log_line, false);
                try {
                    logResp = client.GetLogs(req4);
                } catch (LogException e) {
                    e.printStackTrace();
                }
                if (logResp != null && logResp.IsCompleted()) {
                    ArrayList<QueriedLog> tmpList = logResp.GetLogs();
                    JSONArray tmpArray = transLogForm(tmpList);
                    jsArray.addAll(tmpArray);
                    //logList.addAll(tmpList);
                    break;
                }
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            log_offset += log_line;
        }
        return jsArray;
    }

    /**
     * 转换log  json
     *
     * @param queriedLogs
     * @return JSONArray
     * json key ：
     * <p>
     * "__time__" : 时间戳
     * "__topic__" :主题
     * "level" :
     * "location"
     * "message" : 日志内容
     * "source"   :来源IP
     * "thread" :
     * "time" : 时间
     */
    private static JSONArray transLogForm(ArrayList<QueriedLog> queriedLogs) {
        JSONArray jsArray = new JSONArray();
        for (QueriedLog log : queriedLogs) {
            //AliLogItem logInfo = new AliLogItem();
            JSONObject jsObj = new JSONObject();
            jsObj.put("__source__", log.GetSource());
            jsObj.put("__time__", log.GetLogItem().GetTime());
            for (LogContent content : log.mLogItem.mContents
                    ) {
                jsObj.put(content.GetKey(), content.GetValue());
            }
            jsArray.add(jsObj);
        }
        return jsArray;
    }

    /**
     * 获取投递至OSS的日志
     * @param keyPrefix OSS key 前缀
     * @return JSONArray
     * @throws IOException
     */
    public static JSONArray getOSSLogs(String keyPrefix) throws IOException {
        String nextMarker = null;
        ObjectListing objectListing = null;
        int maxKeys = 100;
        List<OSSObjectSummary> sums = null;
        JSONArray jsonArray = new JSONArray();
        do {
            objectListing = ossClient.listObjects(new ListObjectsRequest(LogProperty.bucketName).
                    withPrefix(keyPrefix).withMarker(nextMarker).withMaxKeys(maxKeys));

            sums = objectListing.getObjectSummaries();
            for (OSSObjectSummary s : sums) {
                OSSObject object = ossClient.getObject(new GetObjectRequest(LogProperty.bucketName, s.getKey()));
                BufferedReader reader = new BufferedReader(new InputStreamReader(object.getObjectContent(),"utf-8"));
                while (true) {
                    String line = reader.readLine();
                    if (line == null) break;
                    JSONObject jsObj = JSON.parseObject(line);
                    jsonArray.add(jsObj);
                }
                reader.close();
            }
            nextMarker = objectListing.getNextMarker();

        } while (objectListing.isTruncated());
        return  jsonArray;
    }
}
